package com.bestcem.xm.qdes.service.impl;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bestcem.xm.common.core.domain.web.XmResultJson;
import com.bestcem.xm.common.core.exception.BusinessException;
import com.bestcem.xm.common.core.oss.enums.OssPathEnum;
import com.bestcem.xm.component.mybatis.service.impl.XmServiceImpl;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.qdes.controller.param.ImageUploadParam;
import com.bestcem.xm.qdes.entity.QdesImageLib;
import com.bestcem.xm.qdes.entity.UploadFileInfo;
import com.bestcem.xm.qdes.entity.UploadFileMap;
import com.bestcem.xm.qdes.enums.FileInfoFTypeEnum;
import com.bestcem.xm.qdes.mapper.QdesImageLibMapper;
import com.bestcem.xm.qdes.mapper.UploadFileInfoMapper;
import com.bestcem.xm.qdes.mapper.UploadFileMapMapper;
import com.bestcem.xm.qdes.service.UploadFileInfoService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class UploadFileInfoServiceImpl extends XmServiceImpl<UploadFileInfoMapper, UploadFileInfo> implements UploadFileInfoService {

    private @NonNull QdesImageLibMapper qdesImagelibMapper;

    private @NonNull UploadFileMapMapper uploadFileMapMapper;

    //private @NonNull OssService ossService;
    private @NonNull StorageService storageService;

    private static final String ROOT_FILE_PATH = System.getProperty("user.dir");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadFileInfo(MultipartFile file, ImageUploadParam imageUploadParam) throws Exception {
        UploadFileInfo uploadFileInfo = new UploadFileInfo();
        String fileInfoId;
        String fileMapId;
        String imageId;
        String filename = file.getOriginalFilename();
        imageUploadParam.setFileName(filename);
        //上传图片格式
        String fileExt = FileTypeUtil.getType(file.getInputStream(), filename);
        String fileId = DigestUtils.md5Hex(file.getInputStream());
        if (imageUploadParam.getKeepext()) {
            fileId = fileId + "." + fileExt;
        }

        //创建查询条件对象
        LambdaQueryWrapper<UploadFileInfo> queryWrapper = Wrappers.lambdaQuery();
        //根据fileId判断图片是否上传过MD5
        queryWrapper
                .eq(UploadFileInfo::getFileId, fileId).last("limit 1");
        UploadFileInfo isExistUploadFileInfo = baseMapper.selectOne(queryWrapper);
        //1.插upload_fileinfo信息
        if (ObjectUtil.isEmpty(isExistUploadFileInfo)) {
            String path = ROOT_FILE_PATH + File.separator + StrUtil.replace(OssPathEnum.TEMP_QDES.getPath(), "/", File.separator);
            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            File image = new File(path, filename);
            file.transferTo(image);
            //上传图片
            //String url = ossService.uploadSimpleFile(image, fileId.substring(5), OssPathEnum.QDES, 0, null, "");
            String url = storageService.upload(image, fileId.substring(5), OssPathEnum.QDES.getPath(), new Dict()).getUrl();

            uploadFileInfo.setFileId(fileId);
            uploadFileInfo.setFileSize((int) image.length());
            uploadFileInfo.setFtype(FileInfoFTypeEnum.FILEINFO_FTYPE_IMAGE.getValue());
            uploadFileInfo.setPolicy(1);
            uploadFileInfo.setUrl(url);
            baseMapper.insert(uploadFileInfo);
            fileInfoId = uploadFileInfo.getId();
            // 删除临时文件
            image.delete();
        } else {
            fileInfoId = isExistUploadFileInfo.getId();
        }
        //2.插upload_filemap信息
        fileMapId = uploadFileMap(fileInfoId, imageUploadParam);

        //3.插qdes_imagelib信息
        imageId = uploadImagelib(fileMapId, imageUploadParam);

        return imageId;
    }

    @Override
    public JSONObject postUpload(MultipartFile file, String systemCode) throws Exception {
        UploadFileInfo uploadFileInfo = new UploadFileInfo();
        String fileInfoId;
        String fileMapId;
        String imageId;
        String url;
        String filename = file.getOriginalFilename();
        ImageUploadParam imageUploadParam = new ImageUploadParam();
        imageUploadParam.setFileName(filename);
        String orgId = SecurityContextHolder.getOrgId();
        String userId = SecurityContextHolder.getUserId();
        imageUploadParam.setOrgId(orgId);
        imageUploadParam.setUserId(userId);
        imageUploadParam.setSystemCode(systemCode);
        imageUploadParam.setKeepext(false);
        //上传图片格式
        String fileExt = FileTypeUtil.getType(file.getInputStream(), filename);
        String fileId = DigestUtils.md5Hex(file.getInputStream());
        if (imageUploadParam.getKeepext()) {
            fileId = fileId + "." + fileExt;
        }

        //创建查询条件对象
        LambdaQueryWrapper<UploadFileInfo> queryWrapper = Wrappers.lambdaQuery();
        //根据fileId判断图片是否上传过MD5
        queryWrapper
                .eq(UploadFileInfo::getFileId, fileId).last("limit 1");
        UploadFileInfo isExistUploadFileInfo = baseMapper.selectOne(queryWrapper);
        //1.插upload_fileinfo信息
        if (ObjectUtil.isEmpty(isExistUploadFileInfo)) {
            String path = ROOT_FILE_PATH + File.separator + StrUtil.replace(OssPathEnum.TEMP_QDES.getPath(), "/", File.separator);
            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            File image = new File(path, filename);
            file.transferTo(image);
            //上传图片
            //url = ossService.uploadSimpleFile(image, fileId.substring(5), OssPathEnum.QDES, 0, null, "");
            url = storageService.upload(image, fileId.substring(5), OssPathEnum.QDES.getPath(), new Dict()).getUrl();

            uploadFileInfo.setFileId(fileId);
            uploadFileInfo.setFileSize((int) image.length());
            uploadFileInfo.setFtype(FileInfoFTypeEnum.FILEINFO_FTYPE_FILE.getValue());
            uploadFileInfo.setPolicy(1);
            uploadFileInfo.setUrl(url);
            baseMapper.insert(uploadFileInfo);
            fileInfoId = uploadFileInfo.getId();
            // 删除临时文件
            image.delete();
        } else {
            fileInfoId = isExistUploadFileInfo.getId();
            url = isExistUploadFileInfo.getUrl();
        }
        //2.插upload_filemap信息
        fileMapId = uploadFileMap(fileInfoId, imageUploadParam);

        //3.插qdes_imagelib信息
        imageId = uploadImagelib(fileMapId, imageUploadParam);

        JSONObject info = new JSONObject();
        info.put("filePath", url);
        info.put("id", fileMapId);
        JSONObject result = new JSONObject();
        result.put("file", info);
        return result;
    }

    @Override
    public String putUpload(MultipartFile file, String id) throws Exception {
        log.info("Now to update upload, id = {}", id);

        UploadFileMap uploadFileMap = uploadFileMapMapper.selectOne(new LambdaQueryWrapper<UploadFileMap>().eq(UploadFileMap::getId, id).last("limit 1"));
        if (uploadFileMap == null) {
            throw new BusinessException("The id is not found");
        }
        UploadFileInfo uploadFileInfo = new UploadFileInfo();
        String fileInfoId;
        String url;
        String filename = file.getOriginalFilename();
        ImageUploadParam imageUploadParam = new ImageUploadParam();
        imageUploadParam.setFileName(filename);
        String orgId = SecurityContextHolder.getOrgId();
        String userId = SecurityContextHolder.getUserId();
        imageUploadParam.setOrgId(orgId);
        imageUploadParam.setUserId(userId);
        imageUploadParam.setKeepext(false);
        //上传图片格式
        String fileExt = FileTypeUtil.getType(file.getInputStream(), filename);
        String fileId = DigestUtils.md5Hex(file.getInputStream());
        if (imageUploadParam.getKeepext()) {
            fileId = fileId + "." + fileExt;
        }

        //创建查询条件对象
        LambdaQueryWrapper<UploadFileInfo> queryWrapper = Wrappers.lambdaQuery();
        //根据fileId判断图片是否上传过MD5
        queryWrapper.eq(UploadFileInfo::getFileId, fileId).last("limit 1");
        UploadFileInfo isExistUploadFileInfo = baseMapper.selectOne(queryWrapper);
        //1.插upload_fileinfo信息
        if (ObjectUtil.isEmpty(isExistUploadFileInfo)) {
            String path = ROOT_FILE_PATH + File.separator + StrUtil.replace(OssPathEnum.TEMP_QDES.getPath(), "/", File.separator);
            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            File image = new File(path, filename);
            file.transferTo(image);
            //上传图片
            //url = ossService.uploadSimpleFile(image, fileId.substring(5), OssPathEnum.QDES, 0, null, "");
            url = storageService.upload(image, fileId.substring(5), OssPathEnum.QDES.getPath(), new Dict()).getUrl();

            uploadFileInfo.setFileId(fileId);
            uploadFileInfo.setFileSize((int) image.length());
            uploadFileInfo.setFtype(FileInfoFTypeEnum.FILEINFO_FTYPE_FILE.getValue());
            uploadFileInfo.setPolicy(1);
            uploadFileInfo.setUrl(url);
            baseMapper.insert(uploadFileInfo);
            fileInfoId = uploadFileInfo.getId();
            // 删除临时文件
            image.delete();
        } else {
            fileInfoId = isExistUploadFileInfo.getId();
            url = isExistUploadFileInfo.getUrl();
        }
        //2.插upload_filemap信息
        List<String> oldFileIds = new ArrayList<>();
        oldFileIds.add(uploadFileMap.getFileInfoId());
        oldFileIds.add(uploadFileMap.getOriginFileInfoId());

        uploadFileMap.setFileInfoId(fileInfoId);
        uploadFileMap.setOriginFileInfoId(fileInfoId);
        uploadFileMap.setFileName(filename);
        uploadFileMapMapper.updateById(uploadFileMap);

        //3.插qdes_imagelib信息
        updateImagelib(id, imageUploadParam);
        // 删除老的文件
        List<String> oldList = oldFileIds.stream().distinct().collect(Collectors.toList());
        for (String oneId : oldList) {
            UploadFileMap uploadFileMap1 = uploadFileMapMapper.selectOne(new LambdaQueryWrapper<UploadFileMap>().eq(UploadFileMap::getFileInfoId, oneId)
                .eq(UploadFileMap::getOriginFileInfoId, oneId).ne(UploadFileMap::getId, id));
            if (uploadFileMap1 == null) {
                baseMapper.deleteById(oneId);
            }
        }
        return url;
    }

    @Override
    public XmResultJson<Object> getFilemapQrcode(String fileMapId) {
        UploadFileMap uploadFileMap = Optional.ofNullable(uploadFileMapMapper.selectOne(new QueryWrapper<UploadFileMap>().lambda().eq(UploadFileMap::getId, fileMapId))).orElseThrow(() -> new BusinessException(String.format("fileMap [id=%s] not found", fileMapId)));
        UploadFileInfo uploadFileInfo = Optional.ofNullable(baseMapper.selectOne(new QueryWrapper<UploadFileInfo>().lambda().eq(UploadFileInfo::getId, uploadFileMap.getFileInfoId()))).orElseThrow(() -> new BusinessException(String.format("fileInfo [id=%s] not found", uploadFileMap.getFileInfoId())));
        String url = uploadFileInfo.getUrl();
        String content = "";
        if (StrUtil.isNotBlank(url) && storageService.exists(url)) {
            content = QrCodeUtil.decode(ImgUtil.read(URLUtil.url(url)));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("content", content);
        return XmResultJson.success(map);
    }

    public String uploadImagelib(String fileMapId, ImageUploadParam imageUploadParam) {
        QdesImageLib qdesImagelib = new QdesImageLib();
        String fileName = imageUploadParam.getFileName();
        qdesImagelib.setTitle(fileName.substring(0, fileName.lastIndexOf(".")));
        //目前只有企业库有上传功能
        qdesImagelib.setIsOfficial(false);
        qdesImagelib.setCompanyId(imageUploadParam.getOrgId());
        qdesImagelib.setCreator(imageUploadParam.getUserId());
        qdesImagelib.setIsCopyDemo(false);
        qdesImagelib.setFilemapId(fileMapId);
        qdesImagelibMapper.insert(qdesImagelib);

        return qdesImagelib.getId();
    }

    public void updateImagelib(String fileMapId, ImageUploadParam imageUploadParam) {
        log.info("Now to updateImagelib");
        String fileName = imageUploadParam.getFileName();
        //目前只有企业库有上传功能
        qdesImagelibMapper.update(null, new LambdaUpdateWrapper<QdesImageLib>()
            .set(QdesImageLib::getTitle, fileName.substring(0, fileName.lastIndexOf(".")))
            .set(QdesImageLib::getDeleted, 0)
            .eq(QdesImageLib::getFilemapId, fileMapId).eq(QdesImageLib::getCompanyId, imageUploadParam.getOrgId()));
    }


    public String uploadFileMap(String fileInfoId, ImageUploadParam imageUploadParam) {
        UploadFileMap uploadFileMap = new UploadFileMap();
        uploadFileMap.setFileName(imageUploadParam.getFileName());
        uploadFileMap.setFileInfoId(fileInfoId);
        uploadFileMap.setOriginFileInfoId(fileInfoId);
        uploadFileMap.setSysId("qdes");

        uploadFileMapMapper.insert(uploadFileMap);

        return uploadFileMap.getId();
    }
}